package com.xmindguoguo.boot.config;

import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.data.transaction.ChainedTransactionManager;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;

import com.alibaba.druid.pool.xa.DruidXADataSource;
import com.baomidou.mybatisplus.MybatisConfiguration;
import com.baomidou.mybatisplus.entity.GlobalConfiguration;
import com.baomidou.mybatisplus.incrementer.OracleKeyGenerator;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
import com.xmindguoguo.boot.config.properties.ConfigurationKit;

import lombok.extern.slf4j.Slf4j;

/**
 * druid 的连接池的配置在这里面
 */
@Configuration
@EnableTransactionManagement
@Slf4j
public class MybatisConfig implements TransactionManagementConfigurer {

    /*配置dataSource，使用Druid连接池*@throws SQLException*/
    @Bean(destroyMethod = "close")
    @Primary
    public DataSource dataSource1() {
        log.info("数据库加载中...............");
        DruidXADataSource dataSource = new DruidXADataSource();
        dataSource.setDriverClassName(ConfigurationKit.CONFIG.getString("jdbc1.driverClassName"));
        dataSource.setUrl(ConfigurationKit.CONFIG.getString("jdbc1.jdbcUrl"));
        dataSource.setUsername(ConfigurationKit.CONFIG.getString("jdbc1.userName"));
        dataSource.setPassword(ConfigurationKit.CONFIG.getString("jdbc1.password"));
        dataSource.setInitialSize(2); // 连接池启动时创建的初始化连接数量（默认值为0）
        dataSource.setMaxActive(5); // 连接池中可同时连接的最大的连接数
        // dataSource.setMaxIdle(12); // 连接池中最大的空闲的连接数，超过的空闲连接将被释放，如果设置为负数表示不限
        dataSource.setMinIdle(0); // 连接池中最小的空闲的连接数，低于这个数量会被创建新的连接
        dataSource.setMaxWait(60000); // 最大等待时间，当没有可用连接时，连接池等待连接释放的最大时间，超过该时间限制会抛出异常，如果设置-1表示无限等待
        dataSource.setRemoveAbandonedTimeout(1000 * 60 * 30); // 超过时间限制，回收没有用(废弃)的连接
        dataSource.setRemoveAbandoned(true); // 超过removeAbandonedTimeout时间后，是否进 行没用连接（废弃）的回收
        dataSource.setTestOnBorrow(false);
        dataSource.setTestOnReturn(false);
        dataSource.setTestWhileIdle(true);
        // dataSource.setValidationQuery("SELECT 1");
        dataSource.setTimeBetweenEvictionRunsMillis(1000 * 60 * 30); // 检查无效连接的时间间隔 设为30分钟
        try {
            dataSource.setFilters("stat");
        } catch (SQLException e) {
            log.warn("配置链接池sql监控出错");
        }
        /*	AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
        	xaDataSource.setXaDataSource(dataSource);
        	xaDataSource.setUniqueResourceName("dataSource1");*/
        return dataSource;
    }

    /**
     * 配置dataSource，使用Druid连接池
     * 
     * @throws SQLException
     */
    @Bean(destroyMethod = "close")
    public DataSource dataSource2() {
        DruidXADataSource dataSource = new DruidXADataSource();
        dataSource.setDriverClassName(ConfigurationKit.CONFIG.getString("jdbc2.driverClassName"));
        dataSource.setUrl(ConfigurationKit.CONFIG.getString("jdbc2.jdbcUrl"));
        dataSource.setUsername(ConfigurationKit.CONFIG.getString("jdbc2.userName"));
        dataSource.setPassword(ConfigurationKit.CONFIG.getString("jdbc2.password"));
        dataSource.setInitialSize(2); // 连接池启动时创建的初始化连接数量（默认值为0）
        dataSource.setMaxActive(5); // 连接池中可同时连接的最大的连接数
        // dataSource.setMaxIdle(12); // 连接池中最大的空闲的连接数，超过的空闲连接将被释放，如果设置为负数表示不限
        dataSource.setMinIdle(0); // 连接池中最小的空闲的连接数，低于这个数量会被创建新的连接
        dataSource.setMaxWait(60000); // 最大等待时间，当没有可用连接时，连接池等待连接释放的最大时间，超过该时间限制会抛出异常，如果设置-1表示无限等待
        dataSource.setRemoveAbandonedTimeout(1000 * 60 * 30); // 超过时间限制，回收没有用(废弃)的连接
        dataSource.setRemoveAbandoned(true); // 超过removeAbandonedTimeout时间后，是否进 行没用连接（废弃）的回收
        dataSource.setTestOnBorrow(false);
        dataSource.setTestOnReturn(false);
        dataSource.setTestWhileIdle(true);
        // dataSource.setValidationQuery("SELECT 1");
        dataSource.setTimeBetweenEvictionRunsMillis(1000 * 60 * 30); // 检查无效连接的时间间隔 设为30分钟
        try {
            dataSource.setFilters("stat");
        } catch (SQLException e) {
            log.warn("配置链接池sql监控出错");
        }
        /*	AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
        	xaDataSource.setXaDataSource(dataSource);
        	xaDataSource.setUniqueResourceName("dataSource2"); */
        return dataSource;
    }

    @Bean
    @Primary
    public SqlSessionFactory sqlSessionFactory1() {
        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setDatabaseId("1");
        bean.setConfiguration(configuration);
        bean.setGlobalConfig(GlobalConfiguration1());
        bean.setDataSource(dataSource1());

        PaginationInterceptor pageHelper = new PaginationInterceptor();
        pageHelper.setDialectType("mysql");
        pageHelper.setLocalPage(true);
        Properties properties = new Properties();
        properties.setProperty("reasonable", "false");
        properties.setProperty("pageSizeZero", "true");
        pageHelper.setProperties(properties);
        bean.setPlugins(new Interceptor[] { pageHelper });
        // bean.setPlugins(plugins);
        // 分页插件
        /*PageHelper pageHelper = new PageHelper();
        Properties properties = new Properties();
        properties.setProperty("dialect", "oracle");
        properties.setProperty("reasonable", "false");
        properties.setProperty("pageSizeZero", "true");
        pageHelper.setProperties(properties);
        bean.setPlugins(new Interceptor[]{pageHelper}); */

        try {
            // 指定mapper xml目录
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            bean.setMapperLocations(resolver.getResources("classpath:mapper/**/*.xml"));
            bean.setTypeAliasesPackage("com.xmindguoguo.boot.modular");
            return bean.getObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Bean
    public GlobalConfiguration GlobalConfiguration1() {
        GlobalConfiguration config = new GlobalConfiguration();
        config.setDbType("mysql");
        config.setKeyGenerator(new OracleKeyGenerator());
        config.setIdType(2);
        // config.setSqlInjector(sqlInjector);
        config.setDbColumnUnderline(false);
        return config;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory2() {

        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
        bean.setGlobalConfig(GlobalConfiguration2());
        bean.setDataSource(dataSource2());

        MybatisConfiguration configuration = new MybatisConfiguration();
        bean.setConfiguration(configuration);
        // 分页插件
        PaginationInterceptor pageHelper = new PaginationInterceptor();
        pageHelper.setDialectType("mysql");
        pageHelper.setLocalPage(true);
        Properties properties = new Properties();
        properties.setProperty("reasonable", "false");
        properties.setProperty("pageSizeZero", "true");
        pageHelper.setProperties(properties);
        bean.setPlugins(new Interceptor[] { pageHelper });

        try {
            // 指定mapper xml目录
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            bean.setMapperLocations(resolver.getResources("classpath:mapper/**/*.xml"));
            bean.setTypeAliasesPackage("com.xmindguoguo.boot.modular");
            return bean.getObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Bean
    public GlobalConfiguration GlobalConfiguration2() {
        GlobalConfiguration config = new GlobalConfiguration();
        config.setDbType("mysql");
        config.setKeyGenerator(new OracleKeyGenerator());
        config.setIdType(2);
        config.setDbColumnUnderline(false);
        return config;
    }

    /**
     * Transaction 相关配置 因为有两个数据源，所有使用ChainedTransactionManager把两个DataSourceTransactionManager包括在一起。
     */

    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        DataSourceTransactionManager dtm1 = new DataSourceTransactionManager(dataSource1());
        DataSourceTransactionManager dtm2 = new DataSourceTransactionManager(dataSource2());
        ChainedTransactionManager ctm = new ChainedTransactionManager(dtm1, dtm2);
        return ctm;
    }

}
